#undef NDEBUG

#include <vector>

#include "InitCGMA.hpp"
#include "CGMApp.hpp"
#include "CubitCompat.hpp"
#include "FacetQueryEngine.hpp"

#include "BodySM.hpp"
#include "Body.hpp"
#include "GeometryQueryTool.hpp"

#include <iostream>

static void print_usage( const char* name, std::ostream& stream )
{
  stream << "Usage: " << name << " <input stl file name> [ <angle (degrees)> <tolerance> <output geometry file name> ] " << std::endl;
  stream << "     default arguments: angle: 135. tolerance: 1.e-6 output file: out.facet \n";
}

int main( int argc, char** argv ) {

  std::vector<CubitString> args;
  CGMApp::instance()->startup(args);

  if (argc<2)
  {
    print_usage(argv[0], std::cout);
    return 0;
  }

  const char* filename = argv[1];
  const char *out_file = "out.facet";

  double angle = 135.;
  if (argc>2)
    angle = atof(argv[2]);

  double tolerance = 1.e-6;
  if (argc>3)
    tolerance = atof(argv[3]);

  if (argc>4)
    out_file = argv[4];

  CubitStatus status = InitCGMA::initialize_cgma();
  if (CUBIT_SUCCESS != status) return 1;

  DLIList<CubitQuadFacet*> quad_facet_list;
  DLIList<CubitFacet*> tri_facet_list;
  DLIList<Surface*> surface_list;
  FacetQueryEngine* fqe = FacetQueryEngine::instance();
  status = fqe->import_facets(filename, CUBIT_TRUE, angle, tolerance, 4, CUBIT_TRUE,
    CUBIT_FALSE, CUBIT_TRUE, CUBIT_TRUE, quad_facet_list, tri_facet_list,
    surface_list, STL_FILE);

  // get bodies, then export to a facet file
  DLIList<Body*> bodies;
  GeometryQueryTool::instance()->bodies(bodies);
  PRINT_INFO(" num bodies: %d\n", bodies.size());
  //BodySM* bodysm_ptr = body_ptr->get_body_sm_ptr();
  DLIList<TopologyBridge*> model;
  for (int j=0; j<bodies.size(); j++)
  {
    BodySM* bodysm_ptr = bodies[j]->get_body_sm_ptr();
    model.append( (TopologyBridge*)bodysm_ptr);
  }
  ModelExportOptions opts;

  fqe->export_solid_model(
        model, out_file, FACET_TYPE,
        CubitString(), opts);
  PRINT_INFO( "converted stl %s to %s \n", filename,  out_file);
  if (CUBIT_SUCCESS != status) return 1;

  return 0;
}
